package cliente;

import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAPackage.WrongPolicy;

import telas.tela_chat;
import telas.tela_login;
import telas.tela_principal;
import ClienteInterfaces.ClienteInterfacePOA;
import ServidorInterfaces.ServidorInterface;
import ServidorInterfaces.ServidorInterfaceHelper;

public class Cliente extends ClienteInterfacePOA {

	private org.omg.CORBA.Object refServerMethod;
	private org.omg.CORBA.Object objRef1;

	//Nome do Cliente
	String nome;
	//Usuario (login)
	String usuario;
	//Senha do Usuario(login)
	String senha;
	//Foto do Cliente
	String foto;
	//Latitude do Usuário
	private double latitude;
	//Longitude do Usuário
	private double longitude;

	private String statusCliente;

	public ServidorInterface instanciaServidor;

	//Lista de usuários que estão visíveis pela distância passada
	private ArrayList<String> usuariosVisiveis;
	//Lista de usuários que estão visíveis pela distância passada
	private ArrayList<String> statusUsuariosVisiveis;
	//Lista de usuários que estão visíveis pela distância passada
	private ArrayList<String> fotosUsuariosVisiveis;
	public ArrayList<Double> latitudesUsuariosVisiveis;
	public ArrayList<Double> longitudesUsuariosVisiveis;

	private tela_principal tela_atual=null;

	//private boolean primeiraVez=true;

	String[] args ;
	//Tenho que ter um array com as telas de bate papo
	private tela_chat inst;//isso é um array para mais de um

	public ArrayList <tela_chat> telas_bate_papo ;


	public Cliente(String[] args , String nome, String usuario, String senha, double latitude, double longitude, boolean cadastro, String status, String foto) {

		this.args=args;
		usuariosVisiveis = new ArrayList<String>();
		telas_bate_papo = new ArrayList<tela_chat>();
		statusUsuariosVisiveis = new ArrayList<String>();
		fotosUsuariosVisiveis = new ArrayList<String>();
		longitudesUsuariosVisiveis= new ArrayList<Double>();
		latitudesUsuariosVisiveis = new ArrayList<Double>();
		this.statusCliente=status;

		//Orb do servidor
		ORB orb = ORB.init(args, null);
		//Orb do cliente
		ORB orb2 = ORB.init(args, null);

		try {

			//Pega a raiz do servidor de nome
			org.omg.CORBA.Object obj = orb.resolve_initial_references("NameService");
			NamingContext naming = NamingContextHelper.narrow(obj);

			//Procura a referência do Servidor que no caso com nome Chat
			NameComponent[] name = { new NameComponent("Chat", "msn_corba") };
			refServerMethod = naming.resolve(name);

			instanciaServidor = ServidorInterfaceHelper.narrow(refServerMethod);

			//Setando as variaveis do cliente:

			setUsuario(usuario);
			setSenha(senha);
			setLatitude(latitude);
			setLongitude(longitude);

			if( cadastro == true ) {
				setNome(nome);
				setFoto(foto);

				//Cadastra cliente
				boolean cadastrar = instanciaServidor.cadastroCliente(nome, usuario, senha, foto);

				if( cadastrar == true ) { 

					//Registra cada cliente no servidor de nomes

					org.omg.CORBA.Object objPoa = orb2.resolve_initial_references("RootPOA");
					POA rootPOA = POAHelper.narrow(objPoa);

					org.omg.CORBA.Object obj1 = orb2.resolve_initial_references("NameService");
					NamingContext naming1 = NamingContextHelper.narrow(obj1);

					//Registra  cliente (como Servidor) para outros terem acesso a ele 
					//pelo nome recebido no teclado
					NameComponent[] name1 = { new NameComponent(usuario, "msn_corba") };
					objRef1 = rootPOA.servant_to_reference(this);
					naming1.rebind(name1, objRef1);
					rootPOA.the_POAManager().activate();

					//	NamingContextnaming.rebind(name1, objRef1); naming1 = NamingContextHelper.narrow(obj1);

					//	System.out.println("digite o nome  do cliente");
					//	setName(new Scanner(System.in).nextLine());
					//	NameComponent[] name1 = { new NameComponent(nameString, "teste") };
					//	naming.rebind(name1, objRef1);

					System.out.println("Cliente criado!");

					JOptionPane.showMessageDialog(null, "Cliente cadastrado!", "Nome", JOptionPane.ERROR_MESSAGE);

				}else{
					JOptionPane.showMessageDialog(null, "Cliente já cadastrado", "Nome", JOptionPane.ERROR_MESSAGE);
					System.out.println("Cliente Já cadastrado!");
				}

			} else {



			}



		} catch (InvalidName e) {
			e.printStackTrace();
		} catch (NotFound e) {
			e.printStackTrace();
		} catch (CannotProceed e) {
			e.printStackTrace();
		} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
			e.printStackTrace();
		} catch (ServantNotActive e) {
			e.printStackTrace();
		} catch (WrongPolicy e) {
			e.printStackTrace();
		} catch (AdapterInactive e) {
			e.printStackTrace();
		}

		/*} else {

			//IMPLEMENTAR AQUI:
			//Quando ele faz o login...

		}*/
	}
	public void atualizaTelaPrincipal(String nome){
		if(this.tela_atual!=null){
			this.tela_atual.atualizaListaUsuarios();
			this.tela_atual.atualizaRadar();}
	}




	//public void setPrimeiraVez(boolean primeiraVez) {
	//	this.primeiraVez = primeiraVez;
	//}


	public tela_chat getInst() {
		return inst;
	}

	public void setInst(tela_chat inst) {
		this.inst = inst;
	}
	public tela_principal getTela_atual() {
		return tela_atual;
	}

	public void setTela_atual(tela_principal tela_atual) {
		this.tela_atual = tela_atual;
	}

	public ArrayList<String> getUsuariosVisiveis() {
		return usuariosVisiveis;
	}

	public ArrayList<String> getFotosVisiveis() {
		return fotosUsuariosVisiveis;
	}

	public String getFoto() {
		return foto;
	}

	public void setFoto(String foto) {
		this.foto = foto;
	}

	public String getStatusCliente() {
		return statusCliente;
	}

	public void setStatusCliente(String statusCliente) {
		this.statusCliente = statusCliente;
	}



	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getUsuario() {
		return usuario;
	}

	public void setUsuario(String usuario) {
		this.usuario = usuario;
	}

	public String getSenha() {
		return senha;
	}

	public void setSenha(String senha) {
		this.senha = senha;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	//Faz o Login do Cliente 
	public boolean fazLoginCliente(){
		//Orb do cliente
		ORB orb2 = ORB.init(args, null);
		//Se fizer o login pega o nome de usuário para registrar na classe:
		if( instanciaServidor.fazLogin(usuario, senha, latitude, longitude,statusCliente) == true ) { 

			setFoto(instanciaServidor.retornaFotoDadoUsuario(usuario));
			setNome(instanciaServidor.retornaNomeDadoUsuario(usuario));

			System.out.println("Logando o cliente e ativando o POA");
			//Ativar o cliente para receber mensagem
			/*org.omg.CORBA.Object objPoa = orb2.resolve_initial_references("RootPOA");
			POA rootPOA = POAHelper.narrow(objPoa);
			objRef1 = rootPOA.servant_to_reference(this);
			rootPOA.the_POAManager().activate();*/

			org.omg.CORBA.Object objPoa;
			try {
				objPoa = orb2.resolve_initial_references("RootPOA");
				POA rootPOA = POAHelper.narrow(objPoa);


				org.omg.CORBA.Object obj1 = orb2.resolve_initial_references("NameService");
				NamingContext naming1 = NamingContextHelper.narrow(obj1);

				//Registra  cliente (como Servidor) para outros terem acesso a ele 
				//pelo nome recebido no teclado
				NameComponent[] name1 = { new NameComponent(usuario, "msn_corba") };
				objRef1 = rootPOA.servant_to_reference(this);
				naming1.rebind(name1, objRef1);
				rootPOA.the_POAManager().activate();

			} catch (InvalidName e) {
				e.printStackTrace();
			} catch (ServantNotActive e) {
				e.printStackTrace();
			} catch (WrongPolicy e) {
				e.printStackTrace();
			} catch (NotFound e) {
				e.printStackTrace();
			} catch (CannotProceed e) {
				e.printStackTrace();
			} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
				e.printStackTrace();
			} catch (AdapterInactive e) {
				e.printStackTrace();
			}

			return true;

		} else {
			JOptionPane.showMessageDialog(null, "Login ou senha incorreta!", "Nome", JOptionPane.ERROR_MESSAGE);
			System.out.println("Login ou senha incorreta!");

			return false;
		}
	}


	public void receiveDataFromServer(String arg2) {
		System.out.println(arg2);	


	}

	//Adiciona um usuário visível
	public void adicionarUsuarioVisivel(String nomeUsu){

		usuariosVisiveis.add(nomeUsu);
	}

	//Remove todos usuários visíveis
	public void removeTodosUsuariosVisiveis() {

		while(usuariosVisiveis.isEmpty()==false){
			usuariosVisiveis.remove(0);
		}

	}

	//Adiciona um usuário visível
	public void adicionarStatusUsuarioVisivel(String estado){

		statusUsuariosVisiveis.add(estado);
	}

	//Remove todos usuários visíveis
	public void removeTodosStatusUsuariosVisiveis() {

		while(statusUsuariosVisiveis.isEmpty()==false){
			statusUsuariosVisiveis.remove(0);
		}
	}

	//Adiciona uma foto visível
	public void adicionarFotoUsuarioVisivel(String foto){

		fotosUsuariosVisiveis.add(foto);
	}

	//Remove todas as fotos visíveis
	public void removeTodosFotoUsuariosVisiveis() {
		while(fotosUsuariosVisiveis.isEmpty()==false){
			fotosUsuariosVisiveis.remove(0);
		}
	}	

	//Adiciona as longitudes visível
	public void adicionarLongitudeUsuarioVisivel(double lon){

		longitudesUsuariosVisiveis.add(lon);
	}

	//Remove todas as longitudes visíveis
	public void removeTodosLongitudeUsuariosVisiveis() {
		while(longitudesUsuariosVisiveis.isEmpty()==false){
			longitudesUsuariosVisiveis.remove(0);
		}
	}	

	//Adiciona as latitudes visível
	public void adicionarLatitudeUsuarioVisivel(double lat){

		latitudesUsuariosVisiveis.add(lat);
	}

	//Remove todas as latitudes visíveis
	public void removeTodosLatitudeUsuariosVisiveis() {
		while(latitudesUsuariosVisiveis.isEmpty()==false){
			latitudesUsuariosVisiveis.remove(0);
		}
	}	

	public static void main(String[] args) {

		tela_login inst = new tela_login(args);
		inst.setLocationRelativeTo(null);
		inst.setVisible(true);

		//Cliente cliente = new Cliente(args);

		//Cria uma comunicação com o servidor
		//ServidorInterface ServidorInterface = ServidorInterfaceHelper.narrow(cliente.refServerMethod);

		//Cadastra um usuário pelo nome que ele passou
		//ServidorInterface.insertClient(client.getName());

		//Cadastra o usuário no servidor com sua localização
		//ServidorInterface.cadastroCliente(nomeCliente, usuario, senha);

		/*
		while (true) {
			//adicionar os usuários visíveis na lista do cliente
			System.out.println("Está buscando usuário visíveis");
			System.out.println("Digite o raio de busca:");
			double raio = Double.parseDouble(new Scanner(System.in).nextLine());
			ServidorInterface.listaUsuariosVisiveis(client.getName(), client.getLatitude(), client.getLongitude(), raio);
			//Mostra o nome dos usuários que estão visíveis
			for (int i = 0; i < client.usuariosVisiveis.size(); i++) {
				System.out.println("Nome usuário no raio de busca "+client.usuariosVisiveis.get(i));
			}

			System.out.println("digite sua mensagem a enviar a todos");
			String aux = new Scanner(System.in).nextLine();
			System.out.println("imprimindo aux " +aux);
			ServidorInterface.sendMessage(aux);

			System.out.println("Digite o nome do usuário");
			String nomeUsu = new Scanner(System.in).nextLine();
			System.out.println("Digite sua mensagem ao usuário:");
			String msg = new Scanner(System.in).nextLine();
			//System.out.println("imprimindo aux " +aux2);
			ServidorInterface.enviarMensagem(nomeUsu, msg);

		}
		 */
	}

	@Override
	public void recebeDadosDoServidor(String nomeClienteQueEstaEnviando,
			String arg2, String fotoClienteQueEstaEnviando) {
		//Perguntar se já existe a tela no cliente se não criar uma nova tela
		boolean criarNovaTela=true;
		int indice=-1;
		for (int i = 0; i < telas_bate_papo.size(); i++) {
			if(telas_bate_papo.get(i).getNomeUsuario().equals(nomeClienteQueEstaEnviando)){
				criarNovaTela=false;
				indice=i;
			}
		}

		if(criarNovaTela==true){
			//Cria uma tela principal
			/*inst = new tela_chat(nomeClienteQueEstaEnviando,this);
			inst.setLocationRelativeTo(null);
			inst.setVisible(true);
			primeiraVez=false;
			inst.getChat_textarea().append(arg2+"\n");*/

			tela_chat novaTela = new tela_chat(nomeClienteQueEstaEnviando,this,fotoClienteQueEstaEnviando);
			novaTela.setLocationRelativeTo(null);
			novaTela.setVisible(true);
			novaTela.getChat_textarea().append(arg2+"\n");
			telas_bate_papo.add(novaTela);

		}else{
			telas_bate_papo.get(indice).getChat_textarea().append(arg2+"\n");
			//inst.getChat_textarea().append(arg2+"\n");

		}
	}

	public ArrayList<String> getStatusVisiveis() {
		return statusUsuariosVisiveis;
	}

	public ArrayList<Double> getLongitudeVisiveis() {
		return longitudesUsuariosVisiveis;
	}

	public ArrayList<Double> getLatitudeVisiveis() {
		return latitudesUsuariosVisiveis;
	}

}
